package com.gmu.uav;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.util.Set;
import java.util.UUID;

import android.app.Activity;
import android.app.Application;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.widget.Toast;

public class ArduinoConnection extends Application {
	
	private static final int REQUEST_ENABLE_BT = 1;
	private static final UUID BLUESMIRF_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
	private ByteBuffer m_OutgoingBuffer = null;
	private ByteBuffer m_IncomingBuffer = null;
	private BluetoothAdapter m_BluetoothAdapter = null;
	private BluetoothDevice m_BlueSmirfDevice = null;
	private BluetoothSocket m_BlueSmirfSocket = null;
	private InputStream m_BlueSmirfIS = null;
	private OutputStream m_BlueSmirfOS = null;
	private Activity m_Caller = null;
	
	public ArduinoConnection()
	{	
		m_BluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
		
		if (m_BluetoothAdapter == null) 
		{
		    Toast.makeText(getApplicationContext(), "This device does not support bluetooth!", Toast.LENGTH_SHORT).show();
		}
	}
	 
	public byte[] getOutgoingBuffer() 
	{
		return m_OutgoingBuffer.array();
	}
	
	public void setOutgoingBuffer(byte[] array) 
	{
		System.arraycopy(array, 0, this.m_OutgoingBuffer.array(), 0, array.length);
	}
	
	public byte[] getIncomingBuffer() 
	{
		return m_IncomingBuffer.array();
	}
	
	public boolean isBluetoothConnected()
	{
		return m_BluetoothAdapter.isEnabled();
	}
	
	public void enableBluetooth(Activity context) 
	{
		m_Caller = context;
		
		if (!m_BluetoothAdapter.isEnabled()) 
		{
		    Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
		    m_Caller.startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
		}
	}
	
	public void disableBluetooth()
	{
		m_BluetoothAdapter.disable();
	}
	
	public void queryPairedDevices()
	{
		Set<BluetoothDevice> pairedDevices = m_BluetoothAdapter.getBondedDevices();
		
		if (pairedDevices.size() > 0) 
		{    
		    for (BluetoothDevice device : pairedDevices) 
		    {
		    	if(device.getAddress().contentEquals("00:06:66:45:16:CC"))
		    	{
		    		connectDevice(device);
		    		return;
		    	} 
		    }
		}
		
		discoverDevices();
	}
	
	public void connectDevice(final BluetoothDevice device)
	{
		 Thread threadConnection = new Thread(new Runnable() 
		 {
			@Override
			public void run() 
			{	
				m_BluetoothAdapter.cancelDiscovery();
				
				try 
				{
					m_BlueSmirfSocket.connect();
					m_BlueSmirfSocket = device.createRfcommSocketToServiceRecord(BLUESMIRF_UUID);
					m_BlueSmirfIS  = m_BlueSmirfSocket.getInputStream();
					m_BlueSmirfOS = m_BlueSmirfSocket.getOutputStream();
				} 
				catch (IOException e) 
				{
					try 
					{
						m_BlueSmirfSocket.close();
					} 
					catch (IOException e1) 
					{
						e1.printStackTrace();
					}
					
					e.printStackTrace();
				}
				
			}	 
		 });
		
		threadConnection.start();
	}
	
	public void discoverDevices()
	{
		final BroadcastReceiver mReceiver = new BroadcastReceiver() 
		{
		    public void onReceive(Context context, Intent intent) 
		    {
		        String action = intent.getAction();
		       		        
		        if (BluetoothDevice.ACTION_FOUND.equals(action)) 
		        {
		            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
		            
		            if(device.getAddress().contentEquals("00:06:66:45:16:CC"))
		            {
		            	connectDevice(device);
			    		return;
		            }
		        }
		    }
		};
		
		IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
		registerReceiver(mReceiver, filter); 
	}
	
	public void retrieveData()
	{
		if(m_BlueSmirfSocket != null)
		{
			if(m_BlueSmirfSocket.isConnected())
			{
				try 
				{	
					for(int i = 0; i < m_BlueSmirfIS.available(); i++)
					{
						m_BlueSmirfIS.read(m_IncomingBuffer.array());
					}
				} 
				catch (IOException e) {
					
					e.printStackTrace();
				}
			}
		}
	}
	
	public void sendCommand(CommandPacket packet)
	{
		if(m_BlueSmirfSocket != null)
		{
			if(m_BlueSmirfSocket.isConnected())
			{
				try 
				{
					m_BlueSmirfOS.write( packet.getCommandBytes() );
					m_BlueSmirfOS.flush();
				} 
				catch (IOException e) 
				{
					e.printStackTrace();
				}
			}
		}
	}
}
